﻿namespace Atomic.Plugins.Security.Repositories
{
    using System.Linq;
    using System.Collections.Generic;
    using System.Data;

    using Atomic.Caching;
    using Atomic.Extensions;
    using Atomic.Data.AdoNet;
    using Atomic.Modules.Security;

    /// <summary>
    /// 权限信息访问器。
    /// </summary>
    public class PermissionRepository : RepositoryBase, IPermissionRepository
    {
        /// <summary>
        /// 角色表名。
        /// </summary>
        private const string ROLE_TABLE_NAME = "atomic_u_roles";

        /// <summary>
        /// 权限表名。
        /// </summary>
        private const string PERMISSION_TABLE_NAME = "atomic_u_permissions";

        /// <summary>
        /// 根据角色编号获得角色信息。
        /// </summary>
        /// <param name="roleId">角色编号。</param>
        /// <returns>角色信息。</returns>
        public Role GetRole(int roleId)
        {
            return this.GetRoles().FirstOrDefault(role => role.Id == roleId);
        }

        /// <summary>
        /// 获得所有角色。
        /// </summary>
        /// <returns>所有角色信息集合。</returns>
        public IEnumerable<Role> GetRoles()
        {
            IList<Role> roles = CacheManager.Current.Get<IList<Role>>(Messages.ALL_ROLE);

            if (roles == null || roles.Count == 0)
            {
                roles = new List<Role>();

                IDictionary<int, string> permissions = new Dictionary<int, string>();

                string sql = "SELECT Id, Name, DisplayName, Type, Permissions FROM " + ROLE_TABLE_NAME;

                using (IDataReader dataReader = this.DataProvider.SqlQuery(sql))
                {
                    Role role = null;

                    while (dataReader.Read())
                    {
                        role = new Role();
                        role.ChangeCurrentIdentity(dataReader.GetInt32(0));
                        role.Name = dataReader.GetString(1);
                        role.DisplayName = dataReader.GetString(2);
                        role.Type = (RoleType)dataReader.GetInt32(3);
                        permissions[role.Id] = dataReader.GetString(4);

                        roles.Add(role);
                    }
                }

                roles.ForEach(role => role.SetPermissions(this.GetPermissions(permissions[role.Id])));

                CacheManager.Current.Set(Messages.ALL_ROLE, roles);
            }

            return roles ?? Enumerable.Empty<Role>();
        }

        /// <summary>
        /// 获得所有权限信息。
        /// </summary>
        /// <returns>权限信息集合。</returns>
        public IEnumerable<Permission> GetPermissions()
        {
            IList<Permission> permissions = CacheManager.Current.Get<IList<Permission>>(Messages.ALL_PERMISSION);

            if (permissions == null || permissions.Count == 0)
            {
                string sql = "SELECT Id, Name, DisplayName, Description FROM " + PERMISSION_TABLE_NAME;

                using (IDataReader dataReader = this.DataProvider.SqlQuery(sql))
                {
                    Permission permission = null;

                    while (dataReader.Read())
                    {
                        if (permissions == null)
                        {
                            permissions = new List<Permission>();
                        }

                        permission = new Permission();

                        permission.Id = dataReader.GetInt32(0);
                        permission.Name = dataReader.GetString(1);
                        permission.DisplayName = dataReader.GetString(2);
                        permission.Description = dataReader.GetString(3);

                        permissions.Add(permission);
                    }
                }

                CacheManager.Current.Set(Messages.ALL_PERMISSION, permissions);
            }

            return permissions ?? Enumerable.Empty<Permission>();
        }

        /// <summary>
        /// 解释权限编号列表字符串来获得权限信息集合。
        /// </summary>
        /// <remarks>
        /// 传入参数是一个由权限编号加上“,”组合而成的字符串。即：1,2,3,4,7
        /// 这里做的是获得这些权限编号对应的权限信息的集合。
        /// </remarks>
        /// <param name="rolePermissions">权限编号列表。</param>
        /// <returns>权限信息集合。</returns>
        private IEnumerable<Permission> GetPermissions(string rolePermissions)
        {
            var allPermissions = this.GetPermissions();

            IList<Permission> permissions = null;

            Permission permission = null;

            if (!string.IsNullOrWhiteSpace(rolePermissions))
            {
                foreach (var rolePermission in rolePermissions.Trim().Split(','))
                {
                    if (rolePermission.IsNumeric())
                    {
                        if (permissions == null)
                        {
                            permissions = new List<Permission>();
                        }

                        permission = allPermissions.SingleOrDefault(p => p.Id == int.Parse(rolePermission));

                        if (permission != null)
                        {
                            permissions.Add(permission);
                        }
                    }
                }
            }

            return permissions ?? Enumerable.Empty<Permission>();
        }
    }
}